/**
 *****************************************************************************
 * @file
 * @brief 系统指令
 * @author taoye
 * @version V0.0.1
 * @date 2021/08/24
 ****************************************************************************
 */
 /* Includes ------------------------------------------------------------------*/

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "drv_f4_ocadc.h"
#include "system.h"
#include "version.h"
#include "cmd_process.h"
#include "ParmManage.h"

/* Private defines -----------------------------------------------------------*/


/* Private Struct  -----------------------------------------------------------*/


/* Private enum    -----------------------------------------------------------*/


/* Private Variable  ---------------------------------------------------------*/
/***********************************************************************************
 * @brief 		版本号查询
 * ex:
 * @par
 * None
 * @retval 应答数据包首地址
 **********************************************************************************/
ack_packet_t * Version_callback(user_packet_t * user)
{
    ack_packet_t *ack;

    // 应答返回数据
    ack = Ack_Malloc(3);
    sscanf(SOFTWARE_VERSION, "V%hhu.%hhu.%hhu", 
    &ack->data[0],
    &ack->data[1],
    &ack->data[2]);

	return ack;
}
/***********************************************************************************
 * @brief 		握手
 * ex:
 * @par
 * None
 * @retval 应答数据包首地址
 **********************************************************************************/
// 定时器句柄，用于断连检测
TimerHandle_t handshakeTimer;

// 定时器超时回调函数
void HandshakeTimeoutCallback(TimerHandle_t xTimer)
{
    // 超时，设置断连标志    
    taskENTER_CRITICAL();
    data_server.isDisconnected = true;
    msm = MSM_IDLE;
    rsm = RSM_IDLE;
    taskEXIT_CRITICAL();
}

// 初始化定时器，设置1分钟超时
void InitHandshakeTimer(void)
{
    // 创建一个1分钟超时的定时器，回调函数为 HandshakeTimeoutCallback
    handshakeTimer = xTimerCreate("HandshakeTimer", pdMS_TO_TICKS(60000), pdFALSE, (void *)0, HandshakeTimeoutCallback);
    
    // 确保定时器创建成功
    if (handshakeTimer != NULL)
    {
        // 启动定时器
        xTimerStart(handshakeTimer, 0);
    }
}

// 重置定时器，当接收到数据包时调用
static void ResetHandshakeTimer(void)
{
    if (handshakeTimer != NULL)
    {
        xTimerReset(handshakeTimer, 0);
    }
}

ack_packet_t * Shakehand_callback(user_packet_t * user)
{
    ack_packet_t *ack;
	
    // 正常收到数据，重置断连标志和定时器
    data_server.isDisconnected = false;
    ResetHandshakeTimer();

    // 返回正常应答数据
    ack = Ack_Malloc(1);
    ack->data[0] = 0x00;
    
	return ack;
}
/***********************************************************************************
 * @brief 		自检
 * ex:
 * @par
 * None
 * @retval 应答数据包首地址
 **********************************************************************************/
ack_packet_t * Selfcheck_callback(user_packet_t * user)
{
    ack_packet_t *ack;

    // 应答返回数据
    ack = Ack_Malloc(1);
	ack->data[0] = 0x00;

	return ack;
}
/***********************************************************************************
 * @brief 		CPU温度
 * ex:
 * @par
 * None
 * @retval 应答数据包首地址
 **********************************************************************************/
ack_packet_t * Cputem_callback(user_packet_t * user)
{
	double adcx = 0;
	float tem = 0;
	
    ack_packet_t *ack;
	// 用户数据处理

    // 应答返回数据
    ack = Ack_Malloc(2);
	
	adcx = Get_Adc_Average(ADC_MCU_TEMP,10);	//读取通道16内部温度传感器通道,10次取平均
	tem = (float)adcx*(3.3/4096);		//电压值
	tem = (tem-0.76f)/0.0025f + 25; //转换为温度值 
	
    uint32_t tem_32 = tem;

    ack->data[0] = (uint8_t)tem;
	ack->data[1] = (uint8_t)(tem * 100) % 100;

	return ack;
}

uint8_t work = 0x01;
/***********************************************************************************
 * @brief 		工作区
 * ex:
 * @par
 * None
 * @retval 应答数据包首地址
 **********************************************************************************/
ack_packet_t * Workspace_callback(user_packet_t * user)
{
    ack_packet_t *ack;
    if(user->style == CMD_SET)    //设置
    {
        // 用户数据处理
        if(user->data[0] == 1)
        {
            set_sys_wokemode(SYS_MODE_WORK);//设置为工作模式
        }
        else if(user->data[0] == 2)
        {
            set_sys_wokemode(SYS_MODE_UPDATA);//设置为升级模式
        }
        else if(user->data[0] == 3)
        {
            set_sys_wokemode(SYS_MODE_DEBUG);//设置为DEBUG模式
        }

        // 应答返回数据
        ack = Ack_Malloc(1);
        ack->data[0] = 0x00;
    }
    else if(user->style == CMD_READ)       //读取
    {
        // 应答返回数据
        ack = Ack_Malloc(1);
        ack->data[0] = 0x01;
    }

	return ack;
}
/***********************************************************************************
 * @brief 		设备信息
 * ex:
 * @par
 * None
 * @retval 应答数据包首地址
 **********************************************************************************/
extern char device_info_msg[];
ack_packet_t * Deviceinf_callback(user_packet_t * user)
{
    ack_packet_t *ack;
	uint8_t num = 0;

	// 用户数据处理
    if(user->style == CMD_SET)    //设置
    {
        // 用户数据处理
        SetDeviceCode((char *)user->data);
        GetDeviceCode();
        PPItemIWrite(PP_DEVICE_INFO, (uint8_t *)device_info_msg, sizeof(DEVICE_INFO));   
        // 应答返回数据
        ack = Ack_Malloc(1);
        ack->data[0] = 0x00;
    }
    else if(user->style == CMD_READ)       //读取
    {
        // 用户数据处理
        num = GetDeviceInfo();
        // 应答返回数据
        ack = Ack_Malloc(num);
        memcpy(ack->data, device_info_msg,num);
    }
	return ack;
}
/***********************************************************************************
 * @brief 		恢复默认参数
 * ex:
 * @par
 * None
 * @retval 应答数据包首地址
 **********************************************************************************/
ack_packet_t * Serial_num_callback(user_packet_t * user)
{
    ack_packet_t *ack;
 
	// 用户数据处理
    if(user->style == CMD_SET)    //设置
    {
        // 用户数据处理
        PPItemIWrite(PP_SERIAL_NUM, &user->data[0], 2);
        
        // 应答返回数据
        ack = Ack_Malloc(1);
        ack->data[0] = 0x00;
    }
    else if(user->style == CMD_READ)       //读取
    {
        // 用户数据处理
        ack = Ack_Malloc(2);
        PPItemRead(PP_SERIAL_NUM, &ack->data[0], 2);
    }
	return ack;
}
/***********************************************************************************
 * @brief 		保存参数到本地
 * ex:
 * @par
 * None
 * @retval 应答数据包首地址
 **********************************************************************************/
ack_packet_t * Savepara_callback(user_packet_t * user)
{
    ack_packet_t *ack;
	// 用户数据处理
    PPItemCopyToDataDevice();
    // 应答返回数据
    ack = Ack_Malloc(1);
	ack->data[0] = 0x00;

	return ack;
}
/***********************************************************************************
 * @brief 		设备重启
 * ex:
 * @par
 * None
 * @retval 应答数据包首地址
 **********************************************************************************/
ack_packet_t * Reboot_callback(user_packet_t * user)
{
    ack_packet_t *ack;
	// 用户数据处理

    // 应答返回数据
    ack = Ack_Malloc(1);
	ack->data[0] = 0x00;
    // 系统复位
    ack->system_reset_flag = 1;

	return ack;
}

/***********************************************************************************
 * @brief 		对时
 * ex:
 * @par
 * None
 * @retval 应答数据包首地址
 **********************************************************************************/
ack_packet_t *Check_time_callback  ( user_packet_t * user )
{
    ack_packet_t *ack;

    // 应答返回数据
    ack = Ack_Malloc(1);
	ack->data[0] = 0x00;

	return ack;    
}

/***********************************************************************************
 * @brief 		读FRAM
 * ex:
 * @par
 * None
 * @retval 应答数据包首地址
 **********************************************************************************/
ack_packet_t *Read_Fram_callback  ( user_packet_t * user )
{
    ack_packet_t *ack;
    uint16_t addr = 0;
    uint16_t len = 0;
    uint8_t read_fram_info[64];
    
	// 用户数据处理
    if(user->style == CMD_READ)       //读取
    {
        // 用户数据处理
        addr = user->data[0] << 8 | user->data[1];

		len=4;    //默认回传4个字节的数据
		
        ack = Ack_Malloc(len);
		PPItemRead(addr, &ack->data[0], len);
//		
//        PPItemRead(addr, read_fram_info, len);
//        memcpy(ack->data, device_info_msg,len);
    }
	return ack;
}


